Add policy hub and platform gateway support for portals#1266
Add policy hub and platform gateway support for portals#1266
Conversation
…atform # Conflicts: # portals/admin/src/main/webapp/site/public/conf/settings.json
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds Platform Gateway management (admin UI, routes, API client methods, token flows) and a Policy Hub client plus integration in publisher (policy resolution, category filtering, UI flags). Also updates gateway types, theme, and numerous locale strings across portals. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant AdminUI as Admin Portal UI
participant API as Backend API
participant PlatformGW as Platform Gateway Service
rect rgba(200,230,255,0.5)
User->>AdminUI: Open "Manage Platform Gateways"
AdminUI->>API: GET /gateways
API-->>AdminUI: Return gateway list (includes platformGatewayId,isActive)
AdminUI->>User: Render list with status
end
rect rgba(200,255,200,0.5)
User->>AdminUI: Edit platform gateway
AdminUI->>API: GET /gateway-environments/:envId
API-->>AdminUI: platformGateway details
AdminUI->>User: Show edit form
end
rect rgba(255,230,200,0.5)
User->>AdminUI: Regenerate token
AdminUI->>API: POST /gateways/{gatewayId}/regenerate-token
API->>PlatformGW: Trigger regeneration
PlatformGW-->>API: Return new token
API-->>AdminUI: New token
AdminUI->>User: Display token commands
end
sequenceDiagram
participant User as User
participant PublisherUI as Publisher Portal UI
participant PolicyHub as Policy Hub Service
participant API as Backend API
rect rgba(220,200,255,0.5)
User->>PublisherUI: Open API Policies (gateway = apiPlatform)
PublisherUI->>PolicyHub: listAllPolicySpecs()
PolicyHub-->>PublisherUI: Policy specs
PublisherUI->>User: Display policies + category filter
end
rect rgba(200,255,230,0.5)
User->>PublisherUI: Select category filter
PublisherUI->>PublisherUI: Filter policies client-side
PublisherUI->>User: Show filtered policies
end
rect rgba(255,220,220,0.5)
User->>PublisherUI: View policy details
PublisherUI->>PolicyHub: getPolicySpec(name,version)
PolicyHub-->>PublisherUI: Return policy spec
PublisherUI->>User: Show policy (download hidden for Hub policies)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR introduces platform gateway support across the admin and publisher portals. It adds a new "Platform Gateway" type to the gateway environment management system, integrates a "Policy Hub" for managing policies associated with platform gateways in the publisher portal, and provides new UI for registering, configuring, and managing platform gateways in the admin portal.
Changes:
- Added Policy Hub integration in the publisher portal for fetching and displaying policies from an external policy hub service for platform gateway APIs, including category-based filtering of policies.
- Added platform gateway management endpoints and UI in the admin portal (list, create, delete, regenerate token) with a new detail/edit view for platform gateways.
- Added
platform-gatewayas a new gateway type option across API creation flows, overview display, and internationalization files.
Reviewed changes
Copilot reviewed 26 out of 28 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
portals/publisher/.../Constants.js |
Replaced AWS gateway type with apiPlatform: 'api-platform' |
portals/publisher/.../defaultTheme.js |
Added platform gateway gradient color |
portals/publisher/.../PolicyList.tsx |
Added category-based policy filtering with multi-select dropdown |
portals/publisher/.../Policies.tsx |
Integrated PolicyHub for fetching policies when API uses platform gateway |
portals/publisher/.../PoliciesExpansion.tsx |
Added resolvePolicySpec helper for PolicyHub-based policy resolution |
portals/publisher/.../PolicyConfigurationEditDrawer.tsx |
Added PolicyHub fallback for fetching policy specs |
portals/publisher/.../ViewPolicy.tsx |
Added PolicyHub-based policy spec retrieval |
portals/publisher/.../PolicyViewForm.tsx |
Conditionally hides source details and attributes for PolicyHub policies |
portals/publisher/.../GeneralDetails.tsx |
Added hideFlowsAndApiTypes prop for PolicyHub policies |
portals/publisher/.../SourceDetails.tsx |
Hides policy download for PolicyHub gateway policies |
portals/publisher/.../AttachedPolicyCard.tsx (shared) |
Added showDownload prop to conditionally show download button |
portals/publisher/.../AttachedPolicyCard.tsx (policies) |
Uses showDownload to hide download for PolicyHub policies |
portals/publisher/.../MetaData.jsx |
Shows "Platform Gateway" label for platform gateway type |
portals/publisher/.../APICreateWithAI.jsx |
Added platform-gateway to gateway details map |
portals/publisher/.../APICreateRoutes.jsx |
Added platform-gateway to gateway details map |
portals/publisher/.../Types.d.ts |
Added category, categories, supportedGateways fields |
portals/publisher/.../settings.json |
Added policyHub configuration section |
portals/publisher/.../en.json |
Added category filter translation key |
portals/admin/.../api.js |
Added CRUD methods for platform gateways |
portals/admin/.../ListGWEnviornments.jsx |
Added status column, platform gateway detection, custom edit button |
portals/admin/.../AddEditGWEnvironment.jsx |
Added platform gateway detail/edit view with token regeneration |
portals/admin/.../index.jsx |
Added routes for PlatformGatewayManagement |
portals/admin/.../RouteMenuMapping.jsx |
Added Platform Gateways navigation entry |
portals/admin/.../ListBase.jsx |
Layout fix for button alignment |
portals/admin/.../settings.json |
Added platformGateway configuration section |
portals/admin/.../en.json |
Added new translation keys for platform gateways |
portals/admin/.../fr.json |
Added new translation keys for platform gateways |
portals/admin/package-lock.json |
Trailing newline fix |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
...ls/publisher/src/main/webapp/source/src/app/components/Apis/Details/NewOverview/MetaData.jsx
Outdated
Show resolved
Hide resolved
portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsx
Outdated
Show resolved
Hide resolved
...er/src/main/webapp/source/src/app/components/Apis/Create/CreateAPIWithAI/APICreateWithAI.jsx
Outdated
Show resolved
Hide resolved
portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/index.jsx
Show resolved
Hide resolved
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/Policies.tsx
Show resolved
Hide resolved
portals/publisher/src/main/webapp/site/public/conf/settings.json
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 18
🧹 Nitpick comments (1)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx (1)
124-153: Consider addingselectedCategoriesto the dependency array or using functional state update.The
useEffectreadsselectedCategories(lines 126, 132, 149-150) but doesn't include it in the dependency array. This can lead to stale closures. While the current implementation works due to the comparison guard beforesetSelectedCategories, the ESLint exhaustive-deps rule would flag this.Consider using a functional state update pattern to avoid the stale closure issue:
Proposed refactor using functional update
useEffect(() => { if (availableCategories.length === 0) { - if (selectedCategories.length > 0) { - setSelectedCategories([]); - } + setSelectedCategories((prev) => (prev.length > 0 ? [] : prev)); return; } - const normalizedSelection = selectedCategories.filter((category) => - availableCategories.includes(category), - ); - let nextSelection = normalizedSelection; - - if (nextSelection.length === 0) { - const defaults = isAIAPI - ? ['AI', 'Guardrails'] - : (isRestAPI ? ['Transformation', 'Security'] : []); - const matchingDefaults = defaults.filter((category) => - availableCategories.includes(category), - ); - if (matchingDefaults.length > 0) { - nextSelection = matchingDefaults; + setSelectedCategories((prev) => { + const normalizedSelection = prev.filter((category) => + availableCategories.includes(category), + ); + let nextSelection = normalizedSelection; + + if (nextSelection.length === 0) { + const defaults = isAIAPI + ? ['AI', 'Guardrails'] + : (isRestAPI ? ['Transformation', 'Security'] : []); + const matchingDefaults = defaults.filter((category) => + availableCategories.includes(category), + ); + if (matchingDefaults.length > 0) { + nextSelection = matchingDefaults; + } } - } - if (nextSelection.length !== selectedCategories.length - || nextSelection.some((category, index) => category !== selectedCategories[index])) { - setSelectedCategories(nextSelection); - } + if (nextSelection.length !== prev.length + || nextSelection.some((category, index) => category !== prev[index])) { + return nextSelection; + } + return prev; + }); }, [availableCategories, isAIAPI, isRestAPI]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx` around lines 124 - 153, The effect reads selectedCategories but doesn't include it in dependencies, risking stale closures and ESLint warnings; update the logic in the useEffect (the useEffect that references availableCategories, isAIAPI, isRestAPI, selectedCategories, and calls setSelectedCategories) to use a functional state update: call setSelectedCategories(prev => { compute normalizedSelection, nextSelection and compare against prev, returning prev or the new array }) so the current selectedCategories value is read from prev instead of the closed-over variable; alternatively, if you prefer not to use a functional updater, add selectedCategories to the dependency array of the useEffect to satisfy exhaustive-deps.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx`:
- Around line 337-341: The added UI and alert strings in
AddEditGWEnvironment.jsx (e.g., the Alert.success/Alert.error messages like
"Gateway registration token regenerated successfully." and "Failed to regenerate
gateway registration token.", and other texts such as "Loading gateway
details...", "Back to Gateways", "Gateway Name", "Generate Key") are hardcoded
English; replace each hardcoded literal with the project's localization API
(e.g., use intl.formatMessage, t(), or the existing i18n helper used elsewhere
in the codebase) and reference appropriate message IDs from the locale bundles
added in this PR; update the Alert.success and Alert.error calls to pass
localized strings instead of raw literals, and ensure all other occurrences in
the file (ranges noted around the diff and lines ~363-364, 404-408, 816-1086)
are converted to use the same localization mechanism so the page respects the
locale bundles.
- Around line 367-400: The call to updateGatewayEnvironment in
AddEditGWEnvironment.jsx omits the provider argument so it falls back to the
default ('wso2') and can overwrite api-platform environments; when performing
header-only saves preserve the existing provider value used in formSaveCallback
by passing the provider through to updateGatewayEnvironment (or by reading it
from the current environment object) so the provider is included after the other
DTOs (additionalPropertiesArrayDTO, permissionsDTO, vhostDTO) in the argument
list; ensure the same provider symbol/name used in formSaveCallback is used here
so provider is not lost on save.
In
`@portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsx`:
- Around line 101-112: The code currently defaults gatewayStatus to 'Active' and
only overwrites it for platform gateways, causing non-platform rows to
incorrectly show a green "Active" chip; change the logic in
ListGWEnviornments.jsx so gatewayStatus starts as null/undefined and is assigned
only when additionalProperties.isActive is explicitly present (e.g., set
gatewayStatus = additionalProperties.isActive === 'true' ? 'Active' : 'Inactive'
only for entries that expose that field), keep the raw nullable value in the
returned object (retain id, isPlatformGateway, gatewayTypeDisplay) and ensure
the UI rendering only shows the status chip when gatewayStatus is non-null;
apply the same fix to the other similar blocks referenced (around the other
ranges 172-181 and 254-263).
- Around line 60-83: The click handler in GatewayEditButton currently falls back
to dataRow.id when building the platform-gateway route; remove that fallback so
we only navigate to /settings/environments/platform-gateways/:id when
additionalProperties.platformGatewayId exists. In handleClick (and the second
identical block around lines 97-110), call
getAdditionalPropertiesAsMap(dataRow.additionalProperties), read
platformGatewayId without defaulting to dataRow.id, and if platformGatewayId
push the platform-gateways path, otherwise push the regular environment edit
path (/settings/environments/{dataRow.id}); update both occurrences of this
logic in GatewayEditButton to ensure consistent routing.
In `@portals/admin/src/main/webapp/source/src/app/data/api.js`:
- Around line 1185-1237: Add the missing requestContentType to the two gateway
methods: in getPlatformGatewayList() and deletePlatformGateway(gatewayId) ensure
the object passed to client.execute includes requestContentType:
'application/json' (same as createPlatformGateway() and
regeneratePlatformGatewayToken()), i.e., update the client.execute call inside
both getPlatformGatewayList and deletePlatformGateway to include
requestContentType: 'application/json'.
In `@portals/publisher/src/main/webapp/site/public/conf/settings.json`:
- Line 53: Update the supportedApiTypes array in settings.json so it includes
the three missing API types used by the codebase constants: add "WEBSUB",
"WEBHOOK", and "ASYNC" to the existing array in the settings.json file (the
supportedApiTypes entry) so it matches the full set of API types used by the
policy filtering logic.
- Around line 50-54: The policyHub configuration in settings.json contains a
hardcoded development URL in the "policyHub.endpoint" value; replace this with
an environment-specific mechanism (e.g., read process env like
POLICY_HUB_ENDPOINT at startup or use environment-specific files such as
settings.prod.json/settings.dev.json) and ensure whatever config loader the app
uses reads that env var or loads the correct file before enabling the
"policyHub" feature; update any deployment docs to require setting
POLICY_HUB_ENDPOINT (or including settings.prod.json) and change uses of
policyHub.endpoint to the resolved runtime value.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/CreateAPIWithAI/APICreateWithAI.jsx`:
- Around line 93-97: The gatewayDetails map currently only contains the
'platform-gateway' key which causes lookups from settings.environment (where
gatewayType may be 'PlatformGateway') to miss and create a custom gateway;
update the gatewayDetails map (the object named gatewayDetails in
APICreateWithAI.jsx) to also include a 'PlatformGateway' entry mapping to the
same value/name/description as 'platform-gateway' or normalize the gatewayType
value (e.g., lowercase/slugify) before performing the lookup in the code that
reads settings.environment; apply the same change or normalization in
APICreateRoutes.jsx where a similar lookup occurs (around the lookup at line 77)
so both components resolve the Platform Gateway identifier consistently.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/AttachedPolicyCard.tsx`:
- Around line 64-65: The code currently sets isPolicyHubGatewayPolicy from
policyObj.supportedGateways
(policyObj.supportedGateways?.includes(CONSTS.GATEWAY_TYPE.apiPlatform)) which
checks capability metadata instead of the active API gateway; change the logic
to derive the flag from the current API's gatewayType (use the same field used
by the drawer, e.g., api.gatewayType or the API prop available in
AttachedPolicyCard) and update both occurrences (the isPolicyHubGatewayPolicy
declaration and the identical check at the later location around line 157) so
showDownload and related behavior use the actual API gateway (compare
api.gatewayType === CONSTS.GATEWAY_TYPE.apiPlatform) rather than
policyObj.supportedGateways.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/Policies.tsx`:
- Around line 241-242: The else-if branch setting gatewayType =
CONSTS.GATEWAY_TYPE.apiPlatform is unreachable because isPolicyHubGateway is
returned early; remove this dead branch from the Policies component logic (look
for the isPolicyHubGateway check and the gatewayType assignment near the current
conditional) or refactor the surrounding conditional so gatewayType
determination is mutually exclusive and consistent with isPolicyHubGateway
(update any code that reads gatewayType accordingly).
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PoliciesExpansion.tsx`:
- Around line 111-119: The current lookup in PoliciesExpansion.tsx only calls
PolicyHub.getPolicySpec when both policyName and policyVersion exist, causing
attachments with a missing ApiPolicy.policyVersion to be dropped; update the
logic to attempt a lookup by name alone when policyVersion is missing (call
PolicyHub.getPolicySpec with { name: policyName, displayName: policyName } or
similar) and if that still yields null, create and return a minimal placeholder
policy object (with name/displayName and a flag like isPlaceholder) so the
attachment remains visible in allPolicies/flow rendering; ensure you update any
callers that rely on version to handle the placeholder case.
- Around line 122-128: The fallback in PoliciesExpansion.tsx always calls
API.getOperationPolicy(...) which prevents resolving attached common policies;
update the logic to call API.getCommonOperationPolicy(...) when the policy is
known to originate from common policies (use the same flag name isCommonPolicy
used by callers that populate originatedFromCommonPolicies). Modify the call
sites that push into originatedFromCommonPolicies to pass isCommonPolicy through
to the place that resolves the policy, and inside PoliciesExpansion (the
function that currently calls API.getOperationPolicy and returns
policyResponse?.body) choose API.getCommonOperationPolicy(policyId, api.id) when
isCommonPolicy is true, otherwise keep API.getOperationPolicy; ensure the
resolved body handling remains the same.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyConfigurationEditDrawer.tsx`:
- Around line 104-116: When loading the policy spec in
PolicyConfigurationEditDrawer (inside the isPolicyHubGateway branch where
PolicyHub.getPolicySpec is called), ensure you fall back to
PolicyHub.toPolicySpec(policyObj) if PolicyHub.getPolicySpec(...) returns
undefined/null; i.e., after awaiting PolicyHub.getPolicySpec({ name:
policyObj.name, version: policyObj.version, displayName: policyObj.displayName
}) assign policySpecVal = result ?? PolicyHub.toPolicySpec(policyObj) so
migrated/deleted policies render, matching the behavior in ViewPolicy.tsx.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsx`:
- Around line 271-299: The TextField for the description in GeneralDetails.tsx
incorrectly reuses id='name', causing duplicate DOM ids; update the TextField's
id to a unique value (e.g., 'description') so it matches the name/data-testid
and preserves proper label association and accessibility; ensure the change is
applied on the TextField with props value={description},
onChange={handleInputChange} and inputProps referencing isViewMode so behavior
remains unchanged.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/SourceDetails.tsx`:
- Around line 89-90: supportedGateways can be undefined, so first normalize it
(e.g., const normalizedSupportedGateways = Array.isArray(supportedGateways) ?
supportedGateways : []) and then replace usages of
supportedGateways.includes(...) with normalizedSupportedGateways.includes(...);
specifically update the computation of isPolicyHubGatewayPolicy (currently using
supportedGateways.includes(CONSTS.GATEWAY_TYPE.apiPlatform)) and reuse
normalizedSupportedGateways for the later checks referenced in this component
(the other .includes calls around Lines 94 and 257).
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx`:
- Around line 223-227: The renderValue callback in PolicyList (the
renderValue={(selected) => ...} block) returns a hardcoded 'All' string; replace
that literal with an i18n lookup by importing and using useIntl in the
PolicyList component and calling intl.formatMessage({ id:
'Apis.Details.Policies.All', defaultMessage: 'All' }) (or use <FormattedMessage
/> equivalent) so the fallback text is internationalized; ensure useIntl is
invoked in the component and the renderValue path uses intl.formatMessage
instead of the hardcoded 'All'.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsx`:
- Around line 60-80: When starting the Policy Hub fetch inside the dialogOpen &&
isPolicyHubGateway branch, clear any stale policySpec up front by calling
setPolicySpec(undefined) (or the empty initial state) before setLoading(true)
and PolicyHub.getPolicySpec; then in the .catch handler,
setPolicySpec(PolicyHub.toPolicySpec(policyObj)) as the local fallback instead
of leaving the previous spec, and keep Alert.error for the user-facing
message—this ensures PolicyHub.getPolicySpec (and functions
PolicyHub.getPolicySpec, PolicyHub.toPolicySpec, setPolicySpec, setLoading,
Alert.error) cannot leave stale data displayed if the fetch fails.
In `@portals/publisher/src/main/webapp/source/src/app/data/Constants.js`:
- Around line 85-89: The project uses two different serialized identifiers for
the same gateway ('platform-gateway' vs the new CONSTS.GATEWAY_TYPE.apiPlatform
= 'api-platform'), causing policy flows to miss APIs; update APICreateRoutes.jsx
(the publisher create flow) and MetaData.jsx (the special-case logic) to emit
and check CONSTS.GATEWAY_TYPE.apiPlatform instead of the literal
'platform-gateway', and update PoliciesExpansion.tsx and PolicyViewForm.tsx to
also accept a fallback for existing records (treat 'platform-gateway' equivalent
to CONSTS.GATEWAY_TYPE.apiPlatform) so both new and existing APIs map to the
same Policy Hub path.
---
Nitpick comments:
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx`:
- Around line 124-153: The effect reads selectedCategories but doesn't include
it in dependencies, risking stale closures and ESLint warnings; update the logic
in the useEffect (the useEffect that references availableCategories, isAIAPI,
isRestAPI, selectedCategories, and calls setSelectedCategories) to use a
functional state update: call setSelectedCategories(prev => { compute
normalizedSelection, nextSelection and compare against prev, returning prev or
the new array }) so the current selectedCategories value is read from prev
instead of the closed-over variable; alternatively, if you prefer not to use a
functional updater, add selectedCategories to the dependency array of the
useEffect to satisfy exhaustive-deps.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7a0f9a37-e6f9-46cb-a308-801bcfe4c283
⛔ Files ignored due to path filters (1)
portals/admin/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (27)
portals/admin/src/main/webapp/site/public/conf/settings.jsonportals/admin/src/main/webapp/site/public/locales/en.jsonportals/admin/src/main/webapp/site/public/locales/fr.jsonportals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsxportals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsxportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsxportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsxportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/index.jsxportals/admin/src/main/webapp/source/src/app/data/api.jsportals/publisher/src/main/webapp/site/public/conf/settings.jsonportals/publisher/src/main/webapp/site/public/locales/en.jsonportals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Create/CreateAPIWithAI/APICreateWithAI.jsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/NewOverview/MetaData.jsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/AttachedPolicyCard.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/Policies.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PoliciesExpansion.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyConfigurationEditDrawer.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/PolicyViewForm.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/SourceDetails.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/Types.d.tsportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsxportals/publisher/src/main/webapp/source/src/app/components/Shared/PoliciesUI/AttachedPolicyCard.tsxportals/publisher/src/main/webapp/source/src/app/data/Constants.jsportals/publisher/src/main/webapp/source/src/app/data/defaultTheme.js
...admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx
Outdated
Show resolved
Hide resolved
...admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx
Outdated
Show resolved
Hide resolved
...s/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsx
Outdated
Show resolved
Hide resolved
...s/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsx
Outdated
Show resolved
Hide resolved
...rc/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsx
Show resolved
Hide resolved
...src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/SourceDetails.tsx
Outdated
Show resolved
Hide resolved
...als/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx
Outdated
Show resolved
Hide resolved
...als/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx (2)
169-170: Clarify empty selection behavior with a comment.The
shouldShowPolicyfunction returnstruewhenselectedCategories.length === 0, meaning "show all". This behavior is correct but not immediately obvious.Suggested documentation
+ // When no categories are selected, show all policies (unfiltered) const shouldShowPolicy = (policy: Policy) => selectedCategories.length === 0 || selectedCategories.includes(getPolicyCategory(policy));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx` around lines 169 - 170, Add a clarifying comment above the shouldShowPolicy function explaining that an empty selectedCategories array is treated as "show all" (i.e., selectedCategories.length === 0 returns true), so the function returns true for all policies when nothing is selected; reference the function name shouldShowPolicy and the helper getPolicyCategory so reviewers can locate and understand the intent.
125-154: Category defaults initialization is well-designed but complex.The useEffect correctly:
- Filters out invalid categories when
availableCategorieschanges- Applies API-type-specific defaults (
AI/Guardrailsfor AIAPI,Transformation/Securityfor REST)- Uses referential equality check (Lines 148-152) to prevent unnecessary re-renders
Consider adding a brief comment explaining the default selection logic for future maintainers.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx` around lines 125 - 154, Add a short inline comment inside the useEffect above the default-selection block explaining the intent and rules for default categories: that when availableCategories is non-empty we filter invalid selections and, if nothing remains, we pick API-type-specific defaults (for isAIAPI choose ['AI','Guardrails'], for isRestAPI choose ['Transformation','Security']) only if those defaults are present in availableCategories—this comment should be placed near the setSelectedCategories callback (referencing useEffect, setSelectedCategories, availableCategories, isAIAPI, isRestAPI) so future maintainers understand the fallback/default logic without changing any behavior.portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsx (1)
124-124: Consider addingisPolicyHubGatewayto the useEffect dependency array.The effect reads
isPolicyHubGatewaybut the dependency array only includesdialogOpen. Ifapi.gatewayTypechanges while the dialog is open, the effect won't re-run with the correct branch logic.Suggested fix
- }, [dialogOpen]); + }, [dialogOpen, isPolicyHubGateway]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsx` at line 124, The useEffect in ViewPolicy currently depends only on dialogOpen but also reads isPolicyHubGateway (derived from api.gatewayType), so add isPolicyHubGateway to the dependency array so the effect re-runs when api.gatewayType changes; locate the useEffect that references dialogOpen and isPolicyHubGateway and include isPolicyHubGateway (or the underlying api.gatewayType) in its dependency list to ensure the branch logic updates correctly while the dialog is open.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@portals/admin/src/main/webapp/site/public/locales/fr.json`:
- Line 160: Several locale entries in the French locale are still in English;
update the keys such as "AdminPages.Gateways.table.header.gatewayStatus" and the
other untranslated keys referenced (around the other ranges) with proper French
translations, e.g., replace the English strings with their French equivalents
for all entries in fr.json (including the blocks around the reported offsets 382
and 509-536); ensure you only change the string values (keep the JSON keys
intact), validate the JSON, and run a quick UI spot-check of the gateway screens
to confirm translations render correctly.
In
`@portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx`:
- Around line 221-236: The fallback platform-gateway object sets no isActive but
downstream rendering treats falsy as "Inactive"; update the fallback created in
the platformGateway lookup (where platformGatewayId is used and
setPlatformGateway is called) to include isActive: null (or undefined) instead
of leaving it ambiguous so the header can render an explicit "Unknown" or hide
the chip; make the same change for the other similar fallback creation (the
other setPlatformGateway call referenced in the diff) so unresolved gateways
have a nullable isActive rather than being interpreted as inactive.
In
`@portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsx`:
- Around line 93-109: The row mapping currently sets human-readable English
strings into gatewayTypeDisplay and gatewayStatus (e.g., 'Platform Gateway',
'Active', 'Inactive'); instead, keep raw values in the model so the renderer can
localize with intl.formatMessage: set gatewayTypeDisplay to a stable token/enum
(e.g., item.gatewayType or 'platform' for platform gateways) and set
gatewayStatus to a raw status flag (e.g., additionalProperties.isActive as
boolean or 'true'/'false' or a constant like 'ACTIVE'/'INACTIVE'), remove
hard-coded English text from the map block inside the
environmentResult.body.list .map (refer to the isPlatformGateway,
platformGatewayId, gatewayTypeDisplay and gatewayStatus symbols) and apply the
same change for the other mapping at 170-181 so the UI renderer can call
intl.formatMessage() to produce localized labels.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsx`:
- Around line 98-104: Update the static section summary text in GeneralDetails
so it respects the hideFlowsAndApiTypes flag: when hideFlowsAndApiTypes is true,
replace or neutralize the sentence that prompts users to "provide applicable
flows" (or similar) and instead show copy that does not reference Applicable
Flows or Supported API Types; use the existing booleans showApplicableFlows /
showSupportedApiTypes (or directly hideFlowsAndApiTypes) to decide which copy to
render so the summary matches the visible fields.
---
Nitpick comments:
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx`:
- Around line 169-170: Add a clarifying comment above the shouldShowPolicy
function explaining that an empty selectedCategories array is treated as "show
all" (i.e., selectedCategories.length === 0 returns true), so the function
returns true for all policies when nothing is selected; reference the function
name shouldShowPolicy and the helper getPolicyCategory so reviewers can locate
and understand the intent.
- Around line 125-154: Add a short inline comment inside the useEffect above the
default-selection block explaining the intent and rules for default categories:
that when availableCategories is non-empty we filter invalid selections and, if
nothing remains, we pick API-type-specific defaults (for isAIAPI choose
['AI','Guardrails'], for isRestAPI choose ['Transformation','Security']) only if
those defaults are present in availableCategories—this comment should be placed
near the setSelectedCategories callback (referencing useEffect,
setSelectedCategories, availableCategories, isAIAPI, isRestAPI) so future
maintainers understand the fallback/default logic without changing any behavior.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsx`:
- Line 124: The useEffect in ViewPolicy currently depends only on dialogOpen but
also reads isPolicyHubGateway (derived from api.gatewayType), so add
isPolicyHubGateway to the dependency array so the effect re-runs when
api.gatewayType changes; locate the useEffect that references dialogOpen and
isPolicyHubGateway and include isPolicyHubGateway (or the underlying
api.gatewayType) in its dependency list to ensure the branch logic updates
correctly while the dialog is open.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0357ae8d-8e53-4887-b6c6-035948c10750
📒 Files selected for processing (19)
portals/admin/src/main/webapp/site/public/locales/en.jsonportals/admin/src/main/webapp/site/public/locales/fr.jsonportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsxportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsxportals/admin/src/main/webapp/source/src/app/data/api.jsportals/publisher/src/main/webapp/site/public/conf/settings.jsonportals/publisher/src/main/webapp/site/public/locales/en.jsonportals/publisher/src/main/webapp/site/public/locales/fr.jsonportals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Create/CreateAPIWithAI/APICreateWithAI.jsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/NewOverview/MetaData.jsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/AttachedPolicyCard.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/Policies.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PoliciesExpansion.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyConfigurationEditDrawer.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/SourceDetails.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
- portals/admin/src/main/webapp/site/public/locales/en.json
- portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsx
- portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/NewOverview/MetaData.jsx
- portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/AttachedPolicyCard.tsx
- portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/CreateAPIWithAI/APICreateWithAI.jsx
- portals/publisher/src/main/webapp/site/public/locales/en.json
...admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx
Outdated
Show resolved
Hide resolved
...s/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsx
Outdated
Show resolved
Hide resolved
...rc/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (7)
portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js (5)
10-13: Hardcoded default endpoint exposes internal infrastructure.The default Policy Hub endpoint appears to be a development/staging URL. Consider either removing the default or using a placeholder that clearly indicates configuration is required.
Proposed fix
-const DEFAULT_POLICY_HUB_ENDPOINT = - 'https://db720294-98fd-40f4-85a1-cc6a3b65bc9a-dev.e1-us-east-azure.choreoapis.dev' + - '/api-platform/policy-hub-api/policy-hub-public/v1.0'; +const DEFAULT_POLICY_HUB_ENDPOINT = '';Then update
getPolicyHubEndpointto throw or warn if no endpoint is configured:const getPolicyHubEndpoint = () => { const configuredEndpoint = Configurations?.app?.policyHub?.endpoint; - const endpoint = configuredEndpoint || DEFAULT_POLICY_HUB_ENDPOINT; + if (!configuredEndpoint) { + console.warn('Policy Hub endpoint is not configured'); + } + const endpoint = configuredEndpoint || ''; return endpoint.replace(/\/$/, ''); };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js` around lines 10 - 13, Replace the hardcoded development URL in DEFAULT_POLICY_HUB_ENDPOINT with a non-sensitive placeholder or null (e.g., a clearly marked placeholder string or undefined) and update getPolicyHubEndpoint to detect the missing config and either throw an error or log a warning instructing the deployer to set the real endpoint; specifically change the DEFAULT_POLICY_HUB_ENDPOINT constant and add validation in the getPolicyHubEndpoint function to fail fast (throw or console.warn) when no endpoint is configured so no internal/staging URL is used by default.
309-328: Add iteration safeguard to pagination loop.If the API returns an incorrect or very large
count, this loop could make excessive requests. Consider adding a maximum iteration limit.Proposed enhancement
const listAllPolicies = async () => { const limit = getPolicyHubLimit(); let offset = 0; let count = 0; const policies = []; + const maxIterations = 100; // Safety limit + let iterations = 0; do { + if (iterations++ >= maxIterations) { + console.warn('listAllPolicies: Maximum iterations reached'); + break; + } // eslint-disable-next-line no-await-in-loop const response = await listPolicies({ offset, limit });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js` around lines 309 - 328, The pagination loop in listAllPolicies can run indefinitely if the API returns a wrong/huge count; add a safeguard by introducing a max iteration/pages guard (e.g., MAX_ITERATIONS or MAX_PAGES) and an iterations counter, increment it each loop and break (or throw a descriptive error) if exceeded; update references in listAllPolicies (limit, offset, count, policies, and the call to listPolicies) so the loop stops after that cap to prevent excessive requests.
265-294: Add timeout to prevent indefinitely hanging requests.The
fetchcall has no timeout configured. Network issues could cause the UI to hang indefinitely while waiting for Policy Hub responses.Proposed fix using AbortController
-const request = async (path, { method = 'GET', params, headers, body } = {}) => { +const DEFAULT_TIMEOUT_MS = 30000; + +const request = async (path, { method = 'GET', params, headers, body, timeout = DEFAULT_TIMEOUT_MS } = {}) => { const endpoint = getPolicyHubEndpoint(); const url = new URL(`${endpoint}${path}`); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null && value !== '') { url.searchParams.append(key, value); } }); } + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), timeout); + - const response = await fetch(url.toString(), { + let response; + try { + response = await fetch(url.toString(), { method, headers: { Accept: 'application/json', ...(headers || {}), }, body, + signal: controller.signal, }); + } finally { + clearTimeout(timeoutId); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js` around lines 265 - 294, The request function currently calls fetch without a timeout; modify request (the async function named request) to use an AbortController: create a controller, pass controller.signal into fetch, start a timer (e.g., from a configurable timeout value or a sensible default) that calls controller.abort() when elapsed, and clear the timer after fetch completes; handle aborts by catching the thrown DOMException/AbortError and rethrowing a clear Error (e.g., "Policy Hub request timed out") while preserving existing error handling for non-OK responses; ensure headers/body/params usage remains unchanged and the abort controller is cleaned up to avoid leaks.
94-115: Consider adding recursion depth limit to prevent stack overflow.
findAttributeArrayandfindSchemaObjectrecursively traverse objects without depth limits. Malformed or malicious policy definitions could cause stack overflow.Proposed enhancement
-const findAttributeArray = (obj) => { +const findAttributeArray = (obj, depth = 0, maxDepth = 20) => { - if (!obj || typeof obj !== 'object') { + if (!obj || typeof obj !== 'object' || depth > maxDepth) { return null; } if (isAttributeArray(obj)) { return obj; } for (const value of Object.values(obj)) { if (isAttributeArray(value)) { return value; } } for (const value of Object.values(obj)) { if (value && typeof value === 'object') { - const nested = findAttributeArray(value); + const nested = findAttributeArray(value, depth + 1, maxDepth); if (nested) { return nested; } } } return null; };Apply similar changes to
findSchemaObject.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js` around lines 94 - 115, The recursive traversals in findAttributeArray (and similarly in findSchemaObject) need a recursion depth limit to avoid stack overflows on malformed inputs; add an optional depth parameter (or use a local MAX_DEPTH constant) and on each recursive call decrement/check it, returning null when depth is exceeded, and update every recursive invocation inside findAttributeArray and findSchemaObject to pass the decremented depth so traversal stops after the limit; ensure the default behavior uses a sensible MAX_DEPTH (e.g., 50) so existing behavior is preserved for normal inputs.
16-17: Unbounded in-memory cache may cause memory issues.The module-level
policyDefinitionCacheandpolicySpecCacheMaps have no size limit or TTL. In long-running sessions with many policies, memory usage could grow unbounded and cached data may become stale.Consider implementing a simple LRU cache with size limits, or at minimum adding a manual cache clear function to the exports:
const clearCaches = () => { policyDefinitionCache.clear(); policySpecCache.clear(); }; export default { // ... existing exports clearCaches, };Also applies to: 354-384
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js` around lines 16 - 17, The module-level Maps policyDefinitionCache and policySpecCache are unbounded and risk memory growth; add a mitigation by either replacing them with a bounded LRU implementation (e.g., a small LRU class used for policyDefinitionCache and policySpecCache) or, minimally, add and export a clearCaches function that calls policyDefinitionCache.clear() and policySpecCache.clear(); update the module's default export (and any referenced functions that assume caches) to include clearCaches so callers can purge caches, and ensure any places noted around lines 354-384 use the new cache API consistently.portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx (2)
174-180: Consider memoizing filtered policy lists.
filterPoliciesForFlowis called multiple times during render. For large policy lists, consider memoizing the filtered results to avoid repeated filtering on each render.Example using useMemo
const filteredRequestPolicies = useMemo( () => ({ common: filterPoliciesForFlow(commonPolicyList, 'request'), api: filterPoliciesForFlow(apiPolicyList, 'request'), }), [commonPolicyList, apiPolicyList, selectedCategories, gatewayType] ); // Similar for response and fault flows🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx` around lines 174 - 180, filterPoliciesForFlow is being run repeatedly during render; wrap the filtered results in useMemo so the arrays are recomputed only when inputs change. Replace repeated calls to filterPoliciesForFlow for each flow (e.g., 'request', 'response', 'fault') and each source list (commonPolicyList, apiPolicyList) with memoized values using useMemo, and include relevant dependencies like commonPolicyList, apiPolicyList, gatewayType and selectedCategories so the cache invalidates correctly; update places that read those filtered lists to use the memoized variables.
149-152: Array comparison may miss order differences.The comparison logic checks if arrays have the same length and same elements at each index, but
nextSelectionmay have elements in a different order thanprev. This could cause unnecessary re-renders or miss updates when order differs but content is the same.Consider using Set-based comparison or sorting
- if (nextSelection.length !== prev.length - || nextSelection.some((category, index) => category !== prev[index])) { + const prevSet = new Set(prev); + const nextSet = new Set(nextSelection); + const areEqual = prevSet.size === nextSet.size + && [...nextSet].every((cat) => prevSet.has(cat)); + if (!areEqual) { return nextSelection; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx` around lines 149 - 152, The current equality check comparing nextSelection and prev by index can miss cases where they contain the same elements in a different order; update the logic around the array comparison (the block that checks nextSelection.length !== prev.length || nextSelection.some(...)) to perform an order-insensitive comparison instead—either convert both arrays to Sets and compare sizes and that every element of one Set exists in the other, or sort both arrays (stable, same comparator) and then compare elements; ensure you still return nextSelection when they differ. Use the existing identifiers nextSelection and prev to locate and replace the comparison.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/PlatformGatewayManagement.jsx`:
- Around line 634-655: The async handlers (handleRoleAddition and similarly
handleRoleDeletion) suffer from stale closure updates on
validRoles/invalidRoles; change all state updates inside their promise
resolution/rejection to use functional state setters (e.g., setValidRoles(prev
=> [...prev, role]) and setInvalidRoles(prev => [...prev, role]) and compute
roleValidity from the current prev values) so each async callback operates on
the latest state rather than captured arrays; update every setValidRoles,
setInvalidRoles and setRoleValidity call in handleRoleAddition (and mirror the
pattern in handleRoleDeletion) to use the functional updater form and derive
roleValidity from the up-to-date prev state.
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsx`:
- Around line 163-166: The handler handleApiTypeChange currently references
isWebsocketSelected before it's declared, causing a temporal dead zone error;
move the declaration/initialization of the isWebsocketSelected variable so it
appears above (or at least before) the handleApiTypeChange function definition,
then update any other usages (e.g., the similar block around lines 175-178) to
reference the already-initialized isWebsocketSelected; ensure
handleApiTypeChange and any related logic read the variable only after it's
defined.
In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js`:
- Around line 31-40: parsePolicyId fails when the policy name contains
POLICY_ID_SEPARATOR because splitting on the separator yields >2 parts; update
parsePolicyId to locate the last occurrence of POLICY_ID_SEPARATOR (e.g., via
lastIndexOf) and split into name = substring before that index and version =
substring after, preserving any separators in the name, then validate non-empty
name/version and return {name, version} or null; reference the parsePolicyId
function and POLICY_ID_SEPARATOR when making the change.
---
Nitpick comments:
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsx`:
- Around line 174-180: filterPoliciesForFlow is being run repeatedly during
render; wrap the filtered results in useMemo so the arrays are recomputed only
when inputs change. Replace repeated calls to filterPoliciesForFlow for each
flow (e.g., 'request', 'response', 'fault') and each source list
(commonPolicyList, apiPolicyList) with memoized values using useMemo, and
include relevant dependencies like commonPolicyList, apiPolicyList, gatewayType
and selectedCategories so the cache invalidates correctly; update places that
read those filtered lists to use the memoized variables.
- Around line 149-152: The current equality check comparing nextSelection and
prev by index can miss cases where they contain the same elements in a different
order; update the logic around the array comparison (the block that checks
nextSelection.length !== prev.length || nextSelection.some(...)) to perform an
order-insensitive comparison instead—either convert both arrays to Sets and
compare sizes and that every element of one Set exists in the other, or sort
both arrays (stable, same comparator) and then compare elements; ensure you
still return nextSelection when they differ. Use the existing identifiers
nextSelection and prev to locate and replace the comparison.
In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js`:
- Around line 10-13: Replace the hardcoded development URL in
DEFAULT_POLICY_HUB_ENDPOINT with a non-sensitive placeholder or null (e.g., a
clearly marked placeholder string or undefined) and update getPolicyHubEndpoint
to detect the missing config and either throw an error or log a warning
instructing the deployer to set the real endpoint; specifically change the
DEFAULT_POLICY_HUB_ENDPOINT constant and add validation in the
getPolicyHubEndpoint function to fail fast (throw or console.warn) when no
endpoint is configured so no internal/staging URL is used by default.
- Around line 309-328: The pagination loop in listAllPolicies can run
indefinitely if the API returns a wrong/huge count; add a safeguard by
introducing a max iteration/pages guard (e.g., MAX_ITERATIONS or MAX_PAGES) and
an iterations counter, increment it each loop and break (or throw a descriptive
error) if exceeded; update references in listAllPolicies (limit, offset, count,
policies, and the call to listPolicies) so the loop stops after that cap to
prevent excessive requests.
- Around line 265-294: The request function currently calls fetch without a
timeout; modify request (the async function named request) to use an
AbortController: create a controller, pass controller.signal into fetch, start a
timer (e.g., from a configurable timeout value or a sensible default) that calls
controller.abort() when elapsed, and clear the timer after fetch completes;
handle aborts by catching the thrown DOMException/AbortError and rethrowing a
clear Error (e.g., "Policy Hub request timed out") while preserving existing
error handling for non-OK responses; ensure headers/body/params usage remains
unchanged and the abort controller is cleaned up to avoid leaks.
- Around line 94-115: The recursive traversals in findAttributeArray (and
similarly in findSchemaObject) need a recursion depth limit to avoid stack
overflows on malformed inputs; add an optional depth parameter (or use a local
MAX_DEPTH constant) and on each recursive call decrement/check it, returning
null when depth is exceeded, and update every recursive invocation inside
findAttributeArray and findSchemaObject to pass the decremented depth so
traversal stops after the limit; ensure the default behavior uses a sensible
MAX_DEPTH (e.g., 50) so existing behavior is preserved for normal inputs.
- Around line 16-17: The module-level Maps policyDefinitionCache and
policySpecCache are unbounded and risk memory growth; add a mitigation by either
replacing them with a bounded LRU implementation (e.g., a small LRU class used
for policyDefinitionCache and policySpecCache) or, minimally, add and export a
clearCaches function that calls policyDefinitionCache.clear() and
policySpecCache.clear(); update the module's default export (and any referenced
functions that assume caches) to include clearCaches so callers can purge
caches, and ensure any places noted around lines 354-384 use the new cache API
consistently.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bb7b4111-fe75-4d9a-a059-41f1e8bcb19f
📒 Files selected for processing (12)
portals/admin/src/main/webapp/site/public/locales/fr.jsonportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsxportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsxportals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/PlatformGatewayManagement.jsxportals/publisher/src/main/webapp/site/public/locales/en.jsonportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/Policies.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PoliciesExpansion.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/SourceDetails.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyList.tsxportals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsxportals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js
🚧 Files skipped from review as they are similar to previous changes (4)
- portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx
- portals/publisher/src/main/webapp/site/public/locales/en.json
- portals/admin/src/main/webapp/site/public/locales/fr.json
- portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Policies/ViewPolicy.tsx
.../src/main/webapp/source/src/app/components/GatewayEnvironments/PlatformGatewayManagement.jsx
Outdated
Show resolved
Hide resolved
...rc/main/webapp/source/src/app/components/Apis/Details/Policies/PolicyForm/GeneralDetails.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
♻️ Duplicate comments (1)
portals/admin/src/main/webapp/site/public/locales/fr.json (1)
160-160:⚠️ Potential issue | 🟡 MinorTranslate the new Platform Gateway strings in
fr.json.These entries are still English, so French users will see untranslated copy throughout the new Platform Gateway flow. Please replace the new values with actual French strings before merging.
Also applies to: 382-382, 508-536
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/admin/src/main/webapp/site/public/locales/fr.json` at line 160, The fr.json locale contains untranslated English strings for the new Platform Gateway flow (e.g. the key "AdminPages.Gateways.table.header.gatewayStatus"); update these entries by replacing the English values with correct French translations for all new Platform Gateway keys in fr.json (including the other untranslated entries noted in the review), ensure JSON remains valid (proper quoting/escaping) and keep the keys unchanged so the UI picks up the translations.
🧹 Nitpick comments (1)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsx (1)
78-89: Consider adding a comment explaining the dual entries.Based on the context in
MetaData.jsx, the backend can return either'api-platform'or'PlatformGateway'as the gateway type. Having both keys ingatewayDetailscorrectly handles this, but future maintainers may not understand why two entries exist for the same gateway.📝 Suggested clarifying comment
}, + // Two entries for Platform Gateway: the canonical constant key ('api-platform') and + // the literal key ('PlatformGateway') to handle both formats returned by the backend. [CONSTS.GATEWAY_TYPE.apiPlatform]: { value: CONSTS.GATEWAY_TYPE.apiPlatform, name: 'Platform Gateway', description: 'API gateway for platform-managed policies.', isNew: false, }, PlatformGateway: { value: CONSTS.GATEWAY_TYPE.apiPlatform, name: 'Platform Gateway', description: 'API gateway for platform-managed policies.', isNew: false, }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsx` around lines 78 - 89, The two identical entries in gatewayDetails (the key CONSTS.GATEWAY_TYPE.apiPlatform and the PlatformGateway key) exist intentionally because the backend can return either 'api-platform' or 'PlatformGateway' (see MetaData.jsx); add a concise inline comment above these entries explaining that both keys map to the same gateway value to handle legacy/alternate backend responses, referencing CONSTS.GATEWAY_TYPE.apiPlatform, PlatformGateway and gatewayDetails so future maintainers understand why both entries are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@portals/admin/src/main/webapp/site/public/locales/fr.json`:
- Line 160: The fr.json locale contains untranslated English strings for the new
Platform Gateway flow (e.g. the key
"AdminPages.Gateways.table.header.gatewayStatus"); update these entries by
replacing the English values with correct French translations for all new
Platform Gateway keys in fr.json (including the other untranslated entries noted
in the review), ensure JSON remains valid (proper quoting/escaping) and keep the
keys unchanged so the UI picks up the translations.
---
Nitpick comments:
In
`@portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsx`:
- Around line 78-89: The two identical entries in gatewayDetails (the key
CONSTS.GATEWAY_TYPE.apiPlatform and the PlatformGateway key) exist intentionally
because the backend can return either 'api-platform' or 'PlatformGateway' (see
MetaData.jsx); add a concise inline comment above these entries explaining that
both keys map to the same gateway value to handle legacy/alternate backend
responses, referencing CONSTS.GATEWAY_TYPE.apiPlatform, PlatformGateway and
gatewayDetails so future maintainers understand why both entries are present.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e07ed824-d046-4242-b80c-e7a05988d13c
📒 Files selected for processing (5)
portals/admin/src/main/webapp/site/public/locales/en.jsonportals/admin/src/main/webapp/site/public/locales/fr.jsonportals/devportal/src/main/webapp/site/public/locales/en.jsonportals/publisher/src/main/webapp/site/public/locales/en.jsonportals/publisher/src/main/webapp/source/src/app/components/Apis/Create/APICreateRoutes.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- portals/publisher/src/main/webapp/site/public/locales/en.json
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js (2)
267-296: Consider adding request timeout to prevent indefinite hangs.The
fetchcall has no timeout. If the Policy Hub server becomes unresponsive, requests will hang indefinitely, potentially blocking UI interactions.Proposed fix using AbortController
+const DEFAULT_REQUEST_TIMEOUT_MS = 30000; + const request = async (path, { method = 'GET', params, headers, body } = {}) => { const endpoint = getPolicyHubEndpoint(); const url = new URL(`${endpoint}${path}`); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null && value !== '') { url.searchParams.append(key, value); } }); } + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), DEFAULT_REQUEST_TIMEOUT_MS); + - const response = await fetch(url.toString(), { + let response; + try { + response = await fetch(url.toString(), { - method, - headers: { - Accept: 'application/json', - ...(headers || {}), - }, - body, - }); + method, + headers: { + Accept: 'application/json', + ...(headers || {}), + }, + body, + signal: controller.signal, + }); + } finally { + clearTimeout(timeoutId); + } if (!response.ok) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js` around lines 267 - 296, The request function can hang because fetch has no timeout; modify request (in PolicyHub.js) to use an AbortController with a configurable timeout (e.g., default 10s) so the fetch is aborted after the timer elapses: create an AbortController, pass its signal into fetch options, set a setTimeout to call controller.abort() and clear the timeout on success, and ensure the thrown error on abort is handled/annotated (preserve existing error handling for response.ok). Keep the existing params/headers/body behavior and add an optional timeout argument to request or use an internal constant.
18-19: Consider adding cache eviction for long-running sessions.The in-memory caches grow unbounded. For most use cases this is acceptable, but in long-running sessions with many policy lookups, memory could accumulate.
A simple LRU cache or TTL-based eviction could be added later if this becomes an issue.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js` around lines 18 - 19, The in-memory maps policyDefinitionCache and policySpecCache grow unbounded; introduce eviction by replacing direct Map usage with a capped/TTL-backed cache wrapper (e.g., an LRU or TTL policy) and update all access points to use the new wrapper’s get/set/delete methods; specifically, create a small cache utility (used by policyDefinitionCache and policySpecCache) that enforces a maxEntries and/or timeToLive, evicts oldest or expired entries on put/get, and exposes the same lookup/insert semantics so functions that reference policyDefinitionCache and policySpecCache can remain unchanged except for using the new cache instance.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js`:
- Around line 12-14: The constant DEFAULT_POLICY_HUB_ENDPOINT in PolicyHub.js is
a hardcoded Choreo dev URL that may leak into production; change the code that
reads settings.policyHub.endpoint to fail fast or at least warn instead of
silently using DEFAULT_POLICY_HUB_ENDPOINT: update the logic around
DEFAULT_POLICY_HUB_ENDPOINT and the settings lookup (policyHub.endpoint) to
throw an explicit error when no endpoint is configured (or emit a clear runtime
warning if you prefer), and document this behavior so deployments must provide
policyHub.endpoint; ensure the change references DEFAULT_POLICY_HUB_ENDPOINT and
the settings.policyHub.endpoint usage so reviewers can find and update all call
sites.
---
Nitpick comments:
In `@portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js`:
- Around line 267-296: The request function can hang because fetch has no
timeout; modify request (in PolicyHub.js) to use an AbortController with a
configurable timeout (e.g., default 10s) so the fetch is aborted after the timer
elapses: create an AbortController, pass its signal into fetch options, set a
setTimeout to call controller.abort() and clear the timeout on success, and
ensure the thrown error on abort is handled/annotated (preserve existing error
handling for response.ok). Keep the existing params/headers/body behavior and
add an optional timeout argument to request or use an internal constant.
- Around line 18-19: The in-memory maps policyDefinitionCache and
policySpecCache grow unbounded; introduce eviction by replacing direct Map usage
with a capped/TTL-backed cache wrapper (e.g., an LRU or TTL policy) and update
all access points to use the new wrapper’s get/set/delete methods; specifically,
create a small cache utility (used by policyDefinitionCache and policySpecCache)
that enforces a maxEntries and/or timeToLive, evicts oldest or expired entries
on put/get, and exposes the same lookup/insert semantics so functions that
reference policyDefinitionCache and policySpecCache can remain unchanged except
for using the new cache instance.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7c47c625-022d-4d44-af43-1b103c425f54
📒 Files selected for processing (2)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/NewOverview/MetaData.jsxportals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js
portals/publisher/src/main/webapp/source/src/app/data/PolicyHub.js
Outdated
Show resolved
Hide resolved
|
@coderabbitai review |
portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/index.jsx
Outdated
Show resolved
Hide resolved
| id: 'Base.RouteMenuMapping.gateways.items.Editing', | ||
| defaultMessage: 'Edit Gateway Environment', | ||
| }), | ||
| path: '/settings/gateways/(.*?)$', |
There was a problem hiding this comment.
Looks like we have been using incorrect paths here . Let's fix those under a separate issue
...sher/src/main/webapp/source/src/app/components/Apis/Details/Policies/DraggablePolicyCard.tsx
Outdated
Show resolved
Hide resolved
portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditVhost.jsx
Outdated
Show resolved
Hide resolved
…atform # Conflicts: # portals/admin/src/main/webapp/site/public/conf/settings.json # portals/publisher/src/main/webapp/site/public/conf/settings.json
…into main-platform
...dmin/src/main/webapp/source/src/app/components/GatewayEnvironments/GatewayTypeOptionCard.jsx
Show resolved
Hide resolved
...s/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsx
Outdated
Show resolved
Hide resolved
...src/main/webapp/source/src/app/components/GatewayEnvironments/UniversalGatewayManagement.jsx
Outdated
Show resolved
Hide resolved
portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx
Outdated
Show resolved
Hide resolved
portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditVhost.jsx
Outdated
Show resolved
Hide resolved
...s/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/ListGWEnviornments.jsx
Outdated
Show resolved
Hide resolved
...ain/webapp/source/src/app/components/GatewayEnvironments/UniversalGatewayQuickStartGuide.jsx
Outdated
Show resolved
Hide resolved
...admin/src/main/webapp/source/src/app/components/GatewayEnvironments/UniversalGatewayUtils.js
Outdated
Show resolved
Hide resolved
...er/src/main/webapp/source/src/app/components/Apis/Create/CreateAPIWithAI/APICreateWithAI.jsx
Outdated
Show resolved
Hide resolved
|
Let's verify the security issue picked by #1266 (comment) |
...admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx
Outdated
Show resolved
Hide resolved
...admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx
Outdated
Show resolved
Hide resolved
| "name": "publisher", | ||
| "lockfileVersion": 3, | ||
| "requires": true, | ||
| "packages": {} | ||
| } | ||
|
|
||
| "name": "publisher", | ||
| "lockfileVersion": 3, | ||
| "requires": true, | ||
| "packages": {} | ||
| } |
There was a problem hiding this comment.
Shall we remove this diff?
…yEnvironments/AddEditGWEnvironment.jsx Co-authored-by: Ashera Silva <30475839+ashera96@users.noreply.github.com>
Fix missing newline at end of package-lock.json
…into main-platform
|



This pull request introduces enhancements for platform gateway support and improves the clarity and consistency of gateway-related UI messages in both English and French locale files, as well as configuration updates. The main changes are grouped into platform gateway additions, UI/UX improvements, and configuration updates.
Platform Gateway Support:
platformGatewayinsettings.jsonto support platform gateway features, including release URL, version, and control plane host.en.jsonandfr.json, such as platform gateway details, status labels, configuration fields, and registration token dialogs. [1] [2] [3] [4]UI/UX Improvements for Gateway Management:
Configuration and Documentation Updates:
docUrlinsettings.jsonand added new platform gateway configuration fields.These changes collectively improve platform gateway integration, enhance user feedback and validation, and provide a more consistent and user-friendly gateway management experience.
Admin Portal
Screen.Recording.2026-03-14.at.9.23.41.AM.mov
Publisher Portal
Screen.Recording.2026-03-16.at.9.53.23.PM.mov